﻿using System.Collections.Generic;
using System;
using System.Text;
using System.Drawing;

namespace Pitaya_IDE
{
	/// <summary>
	/// Line of text
	/// 一行文字
	/// </summary>
	public class Line : IList<Char>
	{
		protected List<Char> chars;

		/// <summary>
		/// 折叠标记
		/// </summary>
		public string FoldingStartMarker { get; set; }
		public string FoldingEndMarker { get; set; }
		/// <summary>
		/// Text of line was changed
		/// 行的文本已更改
		/// </summary>
		public bool IsChanged { get; set; }
		/// <summary>
		/// Time of last visit of caret in this line
		/// 该行最后一次访问插入符号的时间
		/// </summary>
		/// <remarks>This property can be used for forward/backward navigating
		/// 此属性可用于向前/向后导航
		/// </remarks>
		public DateTime LastVisit { get; set; }
		/// <summary>
		/// Background brush.
		/// 背景刷。
		/// </summary>
		public Brush BackgroundBrush { get; set; }
		/// <summary>
		/// Unique ID
		/// 唯一ID
		/// </summary>
		public int UniqueId { get; private set; }
		/// <summary>
		/// Count of needed start spaces for AutoIndent
		/// 自动缩进所需的起始空间计数
		/// </summary>
		public int AutoIndentSpacesNeededCount
		{
			get;
			set;
		}

		internal Line(int uid)
		{
			this.UniqueId = uid;
			chars = new List<Char>();
		}


		/// <summary>
		/// Clears style of chars, delete folding markers
		/// 清除字符样式，删除折叠标记
		/// </summary>
		public void ClearStyle(StyleIndex styleIndex)
		{
			FoldingStartMarker = null;
			FoldingEndMarker = null;
			for (int i = 0; i < Count; i++)
			{
				Char c = this[i];
				c.style &= ~styleIndex;
				this[i] = c;
			}
		}

		/// <summary>
		/// Text of the line
		/// 行的文本
		/// </summary>
		public virtual string Text
		{
			get
			{
				StringBuilder sb = new StringBuilder(Count);
				foreach (Char c in this)
					sb.Append(c.c);
				return sb.ToString();
			}
		}

		/// <summary>
		/// Clears folding markers
		/// 清除折叠标记
		/// </summary>
		public void ClearFoldingMarkers()
		{
			FoldingStartMarker = null;
			FoldingEndMarker = null;
		}

		/// <summary>
		/// Count of start spaces
		/// 起始空间计数  就是哪一个开始
		/// </summary>
		public int StartSpacesCount
		{
			get
			{
				int spacesCount = 0;
				for (int i = 0; i < Count; i++)
					if (this[i].c == ' ')
						spacesCount++;
					else
						break;
				return spacesCount;
			}
		}

		public int IndexOf(Char item)
		{
			return chars.IndexOf(item);
		}

		/// <summary>
		/// 新加入的文本最终就是通过这里加入
		/// </summary>
		/// <param name="index"></param>
		/// <param name="item"></param>
		public void Insert(int index, Char item)//插入一个字符？
		{
			chars.Insert(index, item);//CYY
		}
		
		public void RemoveAt(int index)//删除一个字符
		{
			chars.RemoveAt(index);
		}

		public Char this[int index]
		{
			get
			{
				if (index < 0)
				{
					index = 0;
				}
				else if (chars.Count == 0)
				{
					return new Char(' ');
				}
				else if (index >= chars.Count)
				{
					index = chars.Count - 1;
				}

				return chars[index];//CYY
			}
			set
			{
				chars[index] = value; 
			}
		}

		public void Add(Char item)
		{
			chars.Add(item);
		}

		public void Clear()
		{
			chars.Clear();
		}

		public bool Contains(Char item)
		{
			return chars.Contains(item);
		}

		public void CopyTo(Char[] array, int arrayIndex)
		{
			chars.CopyTo(array, arrayIndex);
		}

		/// <summary>
		/// Chars count
		/// 字符数
		/// </summary>
		public int Count
		{
			get { return chars.Count; }
		}

		public bool IsReadOnly
		{
			get { return false; }
		}

		public bool Remove(Char item)
		{
			return chars.Remove(item);
		}

		public IEnumerator<Char> GetEnumerator()
		{
			return chars.GetEnumerator();
		}

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
			return chars.GetEnumerator() as System.Collections.IEnumerator;
		}

		public virtual void RemoveRange(int index, int count)
		{
			if (index >= Count)
				return;
			chars.RemoveRange(index, Math.Min(Count - index, count));
		}

		public virtual void TrimExcess()
		{
			chars.TrimExcess();
		}

		public virtual void AddRange(IEnumerable<Char> collection)
		{
			chars.AddRange(collection);
		}
	}

	public struct LineInfo
	{
		List<int> cutOffPositions;
		//Y coordinate of line on screen
		//屏幕上线条的Y坐标
		internal int startY;
		internal int bottomPadding;
		//indent of secondary wordwrap strings (in chars)
		//辅助换行字字符串的缩进（以字符为单位）
		internal int wordWrapIndent;
		/// <summary>
		/// Visible state
		/// 可见状态
		/// </summary>
		public VisibleState VisibleState;

		public LineInfo(int startY)
		{
			cutOffPositions = null;
			VisibleState = VisibleState.Visible;
			this.startY = startY;
			bottomPadding = 0;
			wordWrapIndent = 0;
		}
		/// <summary>
		/// Positions for wordwrap cutoffs
		/// </summary>
		public List<int> CutOffPositions
		{
			get
			{
				if (cutOffPositions == null)
					cutOffPositions = new List<int>();
				return cutOffPositions;
			}
		}

		/// <summary>
		/// Count of wordwrap string count for this line
		/// </summary>
		public int WordWrapStringsCount
		{
			get
			{
				switch (VisibleState)
				{
					case VisibleState.Visible:
						if (cutOffPositions == null)
							return 1;
						else
							return cutOffPositions.Count + 1;
					case VisibleState.Hidden: return 0;
					case VisibleState.StartOfHiddenBlock: return 1;
				}

				return 0;
			}
		}

		internal int GetWordWrapStringStartPosition(int iWordWrapLine)
		{
			return iWordWrapLine == 0 ? 0 : CutOffPositions[iWordWrapLine - 1];
		}

		internal int GetWordWrapStringFinishPosition(int iWordWrapLine, Line line)
		{
			if (WordWrapStringsCount <= 0)
				return 0;
			return iWordWrapLine == WordWrapStringsCount - 1 ? line.Count - 1 : CutOffPositions[iWordWrapLine] - 1;
		}

		/// <summary>
		/// Gets index of wordwrap string for given char position
		/// </summary>
		public int GetWordWrapStringIndex(int iChar)
		{
			if (cutOffPositions == null || cutOffPositions.Count == 0) return 0;
			for (int i = 0; i < cutOffPositions.Count; i++)
				if (cutOffPositions[i] >/*>=*/ iChar)
					return i;
			return cutOffPositions.Count;
		}
	}

	public enum VisibleState : byte
	{
		Visible, StartOfHiddenBlock, Hidden
	}

	public enum IndentMarker
	{
		None,
		Increased,
		Decreased
	}
}
